// aiManager.js - AI辅助学习管理器
// 提供单例模式的AI管理器，用于处理与deepseek API的交互
let instance = null;

class AIManager {
  constructor() {
    // deepseek API 基础配置
    this.DEEPSEEK_API_BASE_URL = 'https://api.deepseek.com/v1/chat/completions';
  }
  
  /**
   * 初始化AI管理器
   */
  initialize() {
    const app = getApp();
    // 初始化逻辑，如果需要的话
    console.log('AI管理器初始化成功');
    const appConfig = app.globalData.appConfig;
    // 清理API Key，移除可能的空格、换行符等
    this.apiKey = appConfig.deepseekApiKey.trim();
    this.userMaxCallAICount = appConfig.userMaxCallAICount || 0; // 用户最大调用次数
  }

  /**
   * 获取AI管理器的单例实例
   * @returns {AIManager} AI管理器实例
   */
  static getInstance() {
    if (!instance) {
      instance = new AIManager();
    }
    return instance;
  }

  /**
   * 获取deepseek API Key
   * @returns {string} API Key
   */
  getApiKey() {
    return this.apiKey;
  }

  /**
   * 发送消息到deepseek API
   * @param {Array} messages - 消息数组 [{role: 'user', content: '...'}]
   * @param {Function} onChunk - 流式输出回调函数
   * @param {Object} options - 可选配置
   * @returns {Promise<Object>} API响应结果
   */
  async sendMessage(messages, onChunk, options = {}) {
    try {
      const apiKey = this.getApiKey();
      console.log('准备发送API请求，使用模型:', options.model || 'deepseek-chat');
      
      // 构建请求参数
      const requestData = {
        model: options.model || 'deepseek-chat',
        messages: messages,
        stream: typeof onChunk === 'function',
        max_tokens: options.maxTokens || 1500,
        temperature: options.temperature || 0.7
      };

      if (requestData.stream) {
        try {
          // 尝试流式请求
          console.log('尝试使用流式请求');
          return await this._sendStreamRequest(requestData, apiKey, onChunk);
        } catch (streamError) {
          console.log('流式请求失败，降级到非流式请求:', streamError.message);
          // 降级到非流式请求
          const nonStreamData = { ...requestData, stream: false };
          const result = await this._sendRequest(nonStreamData, apiKey);
          
          // 如果有onChunk回调，将完整响应一次性发送
          if (typeof onChunk === 'function' && result.choices && result.choices[0] && result.choices[0].message) {
            const content = result.choices[0].message.content || '';
            onChunk(content);
          }
          return result;
        }
      } else {
        // 非流式请求处理
        return this._sendRequest(requestData, apiKey);
      }
    } catch (error) {
      console.error('发送消息到AI失败:', error);
      throw error;
    }
  }

  /**
   * 发送非流式请求
   * @private
   * @param {Object} requestData - 请求数据
   * @param {string} apiKey - API Key
   * @returns {Promise<Object>} API响应结果
   */
  async _sendRequest(requestData, apiKey) {
    return new Promise((resolve, reject) => {
      wx.request({
        url: this.DEEPSEEK_API_BASE_URL,
        method: 'POST',
        header: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${apiKey}`
        },
        data: requestData,
        success: (res) => {
          console.log('API响应状态:', res.statusCode);
          if (res.statusCode === 200 && res.data && res.data.choices && res.data.choices[0]) {
            resolve(res.data);
          } else {
            console.error('API返回数据:', res.data);
            reject(new Error(`API请求失败: ${res.statusCode} ${JSON.stringify(res.data)}`));
          }
        },
        fail: (err) => {
          console.error('请求失败:', err);
          reject(err);
        }
      });
    });
  }

  /**
   * 发送流式请求
   * @private
   * @param {Object} requestData - 请求数据
   * @param {string} apiKey - API Key
   * @param {Function} onChunk - 流式输出回调函数
   * @returns {Promise<Object>} 完成结果
   */
  _sendStreamRequest(requestData, apiKey, onChunk) {
    return new Promise((resolve, reject) => {
      console.log('开始流式请求，stream参数:', requestData.stream);
      
      // 设置较短的超时时间以便快速降级
      const timeoutId = setTimeout(() => {
        console.error('流式请求超时，将降级到非流式请求');
        reject(new Error('流式请求超时'));
      }, 10000); // 10秒超时
      
      const task = wx.request({
        url: this.DEEPSEEK_API_BASE_URL,
        method: 'POST',
        responseType: 'text',
        header: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${apiKey}`,
          'Accept': 'text/event-stream'
        },
        enableChunked: true,
        data: requestData,
        success: (res) => {
          console.log('流式请求success回调被触发，这通常不应该发生');
          clearTimeout(timeoutId);
          reject(new Error('流式请求未按预期工作'));
        },
        fail: (err) => {
          console.error('流式请求fail回调被触发:', err);
          clearTimeout(timeoutId);
          reject(err);
        },
        complete: () => {
          console.log('流式请求complete回调被触发');
          clearTimeout(timeoutId);
        }
      });

      // 监听流式响应
      task.onHeadersReceived((res) => {
        console.log('接收到响应头:', res.statusCode);
        // 响应头接收
        if (res.statusCode !== 200) {
          console.error('响应状态码错误:', res.statusCode);
          clearTimeout(timeoutId);
          reject(new Error(`API请求失败: ${res.statusCode}`));
          task.abort();
        }
      });

      task.onChunkReceived((res) => {
          console.log('接收到数据块，数据类型:', typeof res.data, res.data instanceof ArrayBuffer ? 'ArrayBuffer' : '');
          try {
            // 清除超时定时器，说明流式请求正常工作
            clearTimeout(timeoutId);
            
            // 处理每一个数据块
            let chunk = res.data;
            
            // 处理ArrayBuffer类型的数据
            if (res.data instanceof ArrayBuffer) {
              console.log('将ArrayBuffer转换为字符串');
              // 使用更可靠的方式解码UTF-8数据，避免中文乱码
              try {
                // 对于微信小程序环境，我们可以使用更可靠的解码方法
                const bytes = new Uint8Array(res.data);
                let str = '';
                let i = 0;
                
                // 手动解码UTF-8编码，确保中文正确显示
                while (i < bytes.length) {
                  const codePoint = bytes[i];
                  
                  // ASCII字符
                  if (codePoint < 0x80) {
                    str += String.fromCharCode(codePoint);
                    i++;
                  } 
                  // 双字节UTF-8字符
                  else if (codePoint < 0xE0) {
                    const codePoint1 = bytes[i++] & 0x1F;
                    const codePoint2 = bytes[i++] & 0x3F;
                    str += String.fromCharCode((codePoint1 << 6) | codePoint2);
                  } 
                  // 三字节UTF-8字符（大部分中文字符）
                  else if (codePoint < 0xF0) {
                    const codePoint1 = bytes[i++] & 0x0F;
                    const codePoint2 = bytes[i++] & 0x3F;
                    const codePoint3 = bytes[i++] & 0x3F;
                    str += String.fromCharCode((codePoint1 << 12) | (codePoint2 << 6) | codePoint3);
                  } 
                  // 四字节UTF-8字符
                  else {
                    const codePoint1 = bytes[i++] & 0x07;
                    const codePoint2 = bytes[i++] & 0x3F;
                    const codePoint3 = bytes[i++] & 0x3F;
                    const codePoint4 = bytes[i++] & 0x3F;
                    // 处理代理对
                    const codePoint = ((codePoint1 << 18) | (codePoint2 << 12) | (codePoint3 << 6) | codePoint4) - 0x10000;
                    str += String.fromCharCode(0xD800 + (codePoint >> 10), 0xDC00 + (codePoint & 0x3FF));
                  }
                }
                
                chunk = str;
              } catch (e) {
                console.error('解码出错:', e);
                // 降级方案
                chunk = String.fromCharCode.apply(null, new Uint8Array(res.data));
              }
            }
            
            // 确保chunk是字符串类型
            if (typeof chunk !== 'string') {
              console.error('数据块不是字符串类型，类型为:', typeof chunk);
              chunk = String(chunk);
            }
            
            // 处理SSE格式的数据
            const lines = chunk.split('\n');
            for (const line of lines) {
              if (!line || line.startsWith(':')) continue;
              if (line === 'data: [DONE]') {
                // 流式结束
                console.log('流式请求结束');
                resolve({});
                return;
              }
              if (line.startsWith('data: ')) {
                const data = line.substring(6);
                try {
                  const jsonData = JSON.parse(data);
                  if (jsonData.choices && jsonData.choices[0]) {
                    const delta = jsonData.choices[0].delta || {};
                    const content = delta.content || '';
                    if (content && typeof onChunk === 'function') {
                      onChunk(content);
                    }
                  }
                } catch (parseError) {
                  console.error('解析JSON数据失败:', parseError);
                }
              }
            }
          } catch (error) {
            console.error('处理流式响应失败:', error);
            clearTimeout(timeoutId);
            reject(error);
          }
        });
    });
  }

  /**
   * 生成串词成文的提示词
   * @param {Array} selectedWords - 选择的单词数组
   * @param {string} schoolStage - 学段
   * @param {string} grade - 年级
   * @returns {string} 提示词
   */
  generateEssayPrompt(selectedWords, schoolStage, grade) {
    const wordsList = selectedWords.map(word => word.english).join(', ');
    
    return `请使用以下单词创作一篇短文（所有单词必须使用，且不能更改其形式）：${wordsList}

要求：
1. 文章长度适中，内容连贯自然
2. 语言水平适合${schoolStage}${grade}学生
3. 主题积极向上，贴近学生生活
4. 语法正确，用词恰当
5. 请同时提供中文翻译
6. 最后用简短的文字解释文章中使用的重要短语或句型`;
  }

  /**
   * 处理串词成文请求
   * @param {Array} selectedWords - 选择的单词数组
   * @param {string} schoolStage - 学段
   * @param {string} grade - 年级
   * @param {Function} onChunk - 流式输出回调函数
   * @returns {Promise<Object>} API响应结果
   */
  async generateEssay(selectedWords, schoolStage, grade, onChunk) {
    const prompt = this.generateEssayPrompt(selectedWords, schoolStage, grade);
    
    const messages = [
      {
        role: 'system',
        content: '你是一位专业的英语教师，擅长帮助学生学习英语。请根据要求创作英语短文并提供准确的中文翻译。'
      },
      {
        role: 'user',
        content: prompt
      }
    ];

    return this.sendMessage(messages, onChunk, { maxTokens: 2000, temperature: 0.8 });
  }
}

// 导出类和单例实例
module.exports = {
  AIManager,
  getInstance: AIManager.getInstance
};

// 同时设置默认导出为单例实例
module.exports.default = AIManager.getInstance();